<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>数据同步管理</title>
  <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
  <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-icons.css') }}">
  <style>
    .card {
      margin-bottom: 1.5rem;
      box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
    }
    .card-header {
      background-color: #f8f9fa;
      font-weight: 500;
    }
    .btn-icon {
      margin-right: 0.5rem;
    }
    .badge {
      font-size: 0.85rem;
      padding: 0.35rem 0.5rem;
    }
    .table th {
      background-color: #f8f9fa;
    }
    .table-sm td, .table-sm th {
      padding: 0.4rem;
    }
    .code-editor {
      font-family: Consolas, Monaco, 'Andale Mono', monospace;
      border: 1px solid #dee2e6;
      border-radius: 0.25rem;
      padding: 0.5rem;
      min-height: 120px;
      width: 100%;
      background-color: #f8f9fa;
    }
    .preview-table {
      overflow-x: auto;
      max-height: 300px;
    }
    .preview-table thead th {
      position: sticky;
      top: 0;
      background-color: #f8f9fa;
      z-index: 1;
    }
    .progress-bar-animated {
      animation: progress-bar-stripes 1s linear infinite;
    }
    .field-selector {
      height: 150px;
    }
    .status-running {
      color: #0d6efd;
    }
    .status-completed {
      color: #198754;
    }
    .status-failed {
      color: #dc3545;
    }
    .status-pending {
      color: #6c757d;
    }
    .timer {
      font-size: 0.9rem;
      color: #6c757d;
    }
    .nav-tabs .nav-link {
      color: #495057;
    }
    .nav-tabs .nav-link.active {
      font-weight: 500;
    }
  </style>
</head>
<body>
<div class="container mt-4">
  <div class="d-flex justify-content-between align-items-center mb-4">
    <h2>数据同步管理</h2>
    <div>
      <button class="btn btn-outline-primary me-2" data-bs-toggle="modal" data-bs-target="#connectionModal">
        <i class="bi bi-database"></i> 添加数据库
      </button>
      <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#taskModal">
        <i class="bi bi-plus-lg"></i> 新建同步任务
      </button>
    </div>
  </div>

  <!-- 导航选项卡 -->
  <ul class="nav nav-tabs mb-3" id="syncTabs" role="tablist">
    <li class="nav-item" role="presentation">
      <button class="nav-link active" id="tasks-tab" data-bs-toggle="tab" data-bs-target="#tasksTab" type="button" role="tab">
        <i class="bi bi-list-task"></i> 同步任务
      </button>
    </li>
    <li class="nav-item" role="presentation">
      <button class="nav-link" id="connections-tab" data-bs-toggle="tab" data-bs-target="#connectionsTab" type="button" role="tab">
        <i class="bi bi-hdd-network"></i> 数据库连接
      </button>
    </li>
  </ul>

  <!-- 选项卡内容 -->
  <div class="tab-content">
    <!-- 同步任务标签页 -->
    <div class="tab-pane fade show active" id="tasksTab" role="tabpanel">
      <div class="card">
        <div class="card-body p-0">
          <table class="table table-hover mb-0">
            <thead>
              <tr>
                <th>任务名称</th>
                <th>数据库连接</th>
                <th>目标集合</th>
                <th>状态</th>
                <th>上次运行</th>
                <th>操作</th>
              </tr>
            </thead>
            <tbody id="taskList">
              <!-- 动态填充任务列表 -->
            </tbody>
          </table>
        </div>
      </div>
    </div>

    <!-- 数据库连接标签页 -->
    <div class="tab-pane fade" id="connectionsTab" role="tabpanel">
      <div class="card">
        <div class="card-body p-0">
          <table class="table table-hover mb-0">
            <thead>
              <tr>
                <th>连接名称</th>
                <th>数据库类型</th>
                <th>主机</th>
                <th>数据库名</th>
                <th>操作</th>
              </tr>
            </thead>
            <tbody id="connectionList">
              <!-- 动态填充连接列表 -->
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>

  <!-- 数据库连接模态框 -->
  <div class="modal fade" id="connectionModal" tabindex="-1">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">添加数据库连接</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body">
          <form id="connectionForm">
            <div class="mb-3">
              <label class="form-label">连接名称 *</label>
              <input type="text" class="form-control" id="connectionName" required>
            </div>
            <div class="mb-3">
              <label class="form-label">数据库类型 *</label>
              <select class="form-select" id="dbType" required>
                <option value="mysql">MySQL</option>
                <option value="postgresql">PostgreSQL</option>
              </select>
            </div>
            <div class="mb-3">
              <label class="form-label">主机 *</label>
              <input type="text" class="form-control" id="host" required placeholder="例如: localhost 或 127.0.0.1">
            </div>
            <div class="mb-3">
              <label class="form-label">端口 *</label>
              <input type="number" class="form-control" id="port" required>
            </div>
            <div class="mb-3">
              <label class="form-label">用户名 *</label>
              <input type="text" class="form-control" id="username" required>
            </div>
            <div class="mb-3">
              <label class="form-label">密码 *</label>
              <input type="password" class="form-control" id="password" required>
            </div>
            <div class="mb-3">
              <label class="form-label">数据库名 *</label>
              <input type="text" class="form-control" id="database" required>
            </div>
          </form>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
          <button type="button" class="btn btn-primary" id="testConnection">测试连接</button>
          <button type="button" class="btn btn-success" id="saveConnection">保存</button>
        </div>
      </div>
    </div>
  </div>

  <!-- 同步任务模态框 -->
  <div class="modal fade" id="taskModal" tabindex="-1">
    <div class="modal-dialog modal-lg">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">新建同步任务</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body">
          <form id="taskForm">
            <div class="mb-3">
              <label class="form-label">任务名称 *</label>
              <input type="text" class="form-control" id="taskName" required>
            </div>
            
            <div class="mb-3">
              <label class="form-label">数据库连接 *</label>
              <select class="form-select" id="connectionSelect" required>
                <!-- 动态填充数据库连接 -->
              </select>
            </div>
            
            <div class="mb-3">
              <label class="form-label">SQL查询 *</label>
              <textarea class="code-editor" id="sqlQuery" required placeholder="SELECT * FROM your_table"></textarea>
              <div class="d-flex justify-content-end mt-2">
                <button type="button" class="btn btn-sm btn-outline-primary" id="previewQuery">预览查询结果</button>
              </div>
            </div>
            
            <div id="previewArea" class="mb-3 d-none">
              <div class="alert alert-info">
                <i class="bi bi-info-circle"></i> 预览显示最多100条记录
              </div>
              <div class="preview-table">
                <table class="table table-sm table-bordered" id="previewTable">
                  <thead>
                    <tr>
                      <!-- 动态填充表头 -->
                    </tr>
                  </thead>
                  <tbody>
                    <!-- 动态填充数据 -->
                  </tbody>
                </table>
              </div>
            </div>
            
            <div class="mb-3">
              <label class="form-label">知识库 *</label>
              <select class="form-select" id="knowledgeSelect" required>
                <!-- 动态填充知识库列表 -->
              </select>
            </div>
            
            <div class="mb-3">
              <label class="form-label">字段映射</label>
              <div class="row">
                <div class="col-md-4">
                  <label class="form-label">Document字段</label>
                  <select multiple class="form-control field-selector" id="documentFields">
                    <!-- 动态填充字段列表 -->
                  </select>
                  <small class="form-text text-muted">选择作为文档内容的字段</small>
                </div>
                <div class="col-md-4">
                  <label class="form-label">Metadata字段</label>
                  <select multiple class="form-control field-selector" id="metadataFields">
                    <!-- 动态填充字段列表 -->
                  </select>
                  <small class="form-text text-muted">选择作为元数据的字段</small>
                </div>
                <div class="col-md-4">
                  <label class="form-label">Embedding字段</label>
                  <select multiple class="form-control field-selector" id="embeddingFields">
                    <!-- 动态填充字段列表 -->
                  </select>
                  <small class="form-text text-muted">选择用于生成向量的字段</small>
                </div>
              </div>
            </div>
          </form>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
          <button type="button" class="btn btn-success" id="saveTask">创建任务</button>
        </div>
      </div>
    </div>
  </div>

  <!-- 同步进度模态框 -->
  <div class="modal fade" id="progressModal" tabindex="-1" data-bs-backdrop="static">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">同步进度</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body">
          <div class="mb-3">
            <div class="d-flex justify-content-between">
              <span id="progressStatus">正在同步...</span>
              <span class="timer" id="progressTimer">已运行: 00:00:00</span>
            </div>
            <div class="progress mt-2">
              <div class="progress-bar progress-bar-striped progress-bar-animated" 
                  id="progressBar" role="progressbar" style="width: 0%"></div>
            </div>
            <div class="d-flex justify-content-between mt-1">
              <small id="progressCount">0 / 0 条记录</small>
              <small id="progressEta">预计剩余时间: --:--:--</small>
            </div>
          </div>
          <div id="progressError" class="alert alert-danger d-none">
            <!-- 错误信息 -->
          </div>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="closeProgress">关闭</button>
          <button type="button" class="btn btn-danger d-none" id="cancelTask">取消任务</button>
        </div>
      </div>
    </div>
  </div>
</div>

<script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
  // 全局变量
  let availableFields = [];
  let currentTaskRunId = null;
  let progressInterval = null;
  let progressStartTime = null;
  
  // 初始化加载
  loadConnections();
  loadTasks();
  loadKnowledgeList();  // 添加加载知识库列表
  
  // 加载知识库列表
  function loadKnowledgeList() {
    fetch('/api/knowledges')
      .then(response => response.json())
      .then(knowledges => {
        const knowledgeSelect = document.getElementById('knowledgeSelect');
        knowledgeSelect.innerHTML = knowledges.map(k => 
          `<option value="${k.id}">${k.name}</option>`
        ).join('');
      })
      .catch(error => {
        console.error('Error:', error);
      });
  }
  
  // 测试连接按钮点击事件
  document.getElementById('testConnection').addEventListener('click', function() {
    const connectionData = getConnectionFormData();
    if (!validateConnectionForm()) {
      return;
    }
    
    fetch('/api/sync/connections/test', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify(connectionData)
    })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        alert('连接失败: ' + data.error);
      } else {
        alert('连接成功: ' + data.message);
      }
    })
    .catch(error => {
      console.error('Error:', error);
      alert('请求失败，请检查网络连接');
    });
  });
  
  // 保存连接按钮点击事件
  document.getElementById('saveConnection').addEventListener('click', function() {
    const connectionData = getConnectionFormData();
    if (!validateConnectionForm()) {
      return;
    }
    
    fetch('/api/sync/connections', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify(connectionData)
    })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        alert('保存失败: ' + data.error);
      } else {
        bootstrap.Modal.getInstance(document.getElementById('connectionModal')).hide();
        loadConnections();
        document.getElementById('connectionForm').reset();
      }
    })
    .catch(error => {
      console.error('Error:', error);
      alert('请求失败，请检查网络连接');
    });
  });
  
  // 预览查询按钮点击事件
  document.getElementById('previewQuery').addEventListener('click', function() {
    const connectionId = document.getElementById('connectionSelect').value;
    const sqlQuery = document.getElementById('sqlQuery').value;
    
    if (!connectionId) {
      alert('请选择数据库连接');
      return;
    }
    
    if (!sqlQuery) {
      alert('请输入SQL查询');
      return;
    }
    
    fetch('/api/sync/preview', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({
        connection_id: connectionId,
        sql_query: sqlQuery
      })
    })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        alert('查询失败: ' + data.error);
      } else {
        displayPreviewResults(data);
      }
    })
    .catch(error => {
      console.error('Error:', error);
      alert('请求失败，请检查网络连接');
    });
  });
  
  // 保存任务按钮点击事件
  document.getElementById('saveTask').addEventListener('click', function() {
    if (!validateTaskForm()) {
      return;
    }
    
    const taskData = {
      name: document.getElementById('taskName').value,
      database_connection_id: document.getElementById('connectionSelect').value,
      sql_query: document.getElementById('sqlQuery').value,
      knowledge_id: document.getElementById('knowledgeSelect').value,
      document_fields: getSelectedOptions('documentFields'),
      metadata_fields: getSelectedOptions('metadataFields'),
      embedding_fields: getSelectedOptions('embeddingFields')
    };
    
    fetch('/api/sync/tasks', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify(taskData)
    })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        alert('创建失败: ' + data.error);
      } else {
        bootstrap.Modal.getInstance(document.getElementById('taskModal')).hide();
        loadTasks();
        document.getElementById('taskForm').reset();
      }
    })
    .catch(error => {
      console.error('Error:', error);
      alert('请求失败，请检查网络连接');
    });
  });
  
  // 取消任务按钮点击事件
  document.getElementById('cancelTask').addEventListener('click', function() {
    if (!confirm('确定要取消当前运行的任务吗？')) {
      return;
    }
    
    fetch(`/api/sync/tasks/${currentTaskId}/cancel`, {
      method: 'POST'
    })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        alert('取消失败: ' + data.error);
      } else {
        clearInterval(progressInterval);
        loadTasks();
      }
    })
    .catch(error => {
      console.error('Error:', error);
      alert('请求失败，请检查网络连接');
    });
  });
  
  // 辅助函数
  function loadConnections() {
    fetch('/api/sync/connections')
      .then(response => response.json())
      .then(connections => {
        // 更新连接列表
        const connectionList = document.getElementById('connectionList');
        if (connections.length === 0) {
          connectionList.innerHTML = '<tr><td colspan="5" class="text-center">暂无数据库连接</td></tr>';
        } else {
          connectionList.innerHTML = connections.map(conn => `
            <tr>
              <td>${conn.name}</td>
              <td>${conn.db_type}</td>
              <td>${conn.host}:${conn.port}</td>
              <td>${conn.database}</td>
              <td>
                <button class="btn btn-sm btn-outline-danger" onclick="deleteConnection(${conn.id})">
                  <i class="bi bi-trash"></i>
                </button>
              </td>
            </tr>
          `).join('');
        }
        
        // 更新任务创建表单中的连接选择器
        const connectionSelect = document.getElementById('connectionSelect');
        connectionSelect.innerHTML = connections.map(conn => 
          `<option value="${conn.id}">${conn.name} (${conn.db_type})</option>`
        ).join('');
      })
      .catch(error => {
        console.error('Error:', error);
      });
  }
  
  function loadTasks() {
    fetch('/api/sync/tasks')
      .then(response => response.json())
      .then(tasks => {
        const taskList = document.getElementById('taskList');
        if (tasks.length === 0) {
          taskList.innerHTML = '<tr><td colspan="6" class="text-center">暂无同步任务</td></tr>';
        } else {
          taskList.innerHTML = tasks.map(task => {
            const statusClass = getStatusClass(task.status);
            const lastRunDate = task.last_run_at ? new Date(task.last_run_at).toLocaleString() : '从未运行';
            
            return `
              <tr>
                <td>${task.name}</td>
                <td>${task.connection_name || '未知'} (${task.db_type || '未知'})</td>
                <td>${task.chroma_collection_name}</td>
                <td><span class="${statusClass}">${getStatusText(task.status)}</span></td>
                <td>${lastRunDate}</td>
                <td>
                  <div class="btn-group">
                    <button class="btn btn-sm btn-outline-primary" onclick="startTask(${task.id})">
                      <i class="bi bi-play-fill"></i>
                    </button>
                    <button class="btn btn-sm btn-outline-danger" onclick="deleteTask(${task.id})">
                      <i class="bi bi-trash"></i>
                    </button>
                  </div>
                </td>
              </tr>
            `;
          }).join('');
        }
      })
      .catch(error => {
        console.error('Error:', error);
      });
  }
  
  function displayPreviewResults(data) {
    const previewArea = document.getElementById('previewArea');
    const previewTable = document.getElementById('previewTable');
    const previewHead = previewTable.querySelector('thead tr');
    const previewBody = previewTable.querySelector('tbody');
    
    // 显示预览区域
    previewArea.classList.remove('d-none');
    
    // 更新可用字段列表
    availableFields = data.columns;
    updateFieldSelectors(data.columns);
    
    // 生成表头
    previewHead.innerHTML = data.columns.map(col => `<th>${col}</th>`).join('');
    
    // 生成表内容
    if (data.data.length === 0) {
      previewBody.innerHTML = '<tr><td colspan="' + data.columns.length + '" class="text-center">查询结果为空</td></tr>';
    } else {
      previewBody.innerHTML = data.data.map(row => 
        '<tr>' + data.columns.map(col => `<td>${row[col] || ''}</td>`).join('') + '</tr>'
      ).join('');
    }
  }
  
  function updateFieldSelectors(fields) {
    const selectors = ['documentFields', 'metadataFields', 'embeddingFields'];
    
    selectors.forEach(selectorId => {
      const selector = document.getElementById(selectorId);
      selector.innerHTML = fields.map(field => 
        `<option value="${field}">${field}</option>`
      ).join('');
    });
  }
  
  function getConnectionFormData() {
    return {
      name: document.getElementById('connectionName').value,
      db_type: document.getElementById('dbType').value,
      host: document.getElementById('host').value,
      port: document.getElementById('port').value,
      username: document.getElementById('username').value,
      password: document.getElementById('password').value,
      database: document.getElementById('database').value
    };
  }
  
  function validateConnectionForm() {
    const form = document.getElementById('connectionForm');
    if (!form.checkValidity()) {
      form.reportValidity();
      return false;
    }
    return true;
  }
  
  function validateTaskForm() {
    const form = document.getElementById('taskForm');
    if (!form.checkValidity()) {
      form.reportValidity();
      return false;
    }
    return true;
  }
  
  function getSelectedOptions(selectId) {
    const select = document.getElementById(selectId);
    return Array.from(select.selectedOptions).map(option => option.value);
  }
  
  function getStatusClass(status) {
    switch (status) {
      case 'running': return 'status-running';
      case 'completed': return 'status-completed';
      case 'failed': return 'status-failed';
      default: return 'status-pending';
    }
  }
  
  function getStatusText(status) {
    switch (status) {
      case 'running': return '运行中';
      case 'completed': return '已完成';
      case 'failed': return '失败';
      case 'cancelled': return '已取消';
      default: return '等待中';
    }
  }
  
  function formatTime(seconds) {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = Math.floor(seconds % 60);
    
    return [
      hours.toString().padStart(2, '0'),
      minutes.toString().padStart(2, '0'),
      secs.toString().padStart(2, '0')
    ].join(':');
  }
  
  // 删除连接函数
  window.deleteConnection = function(connectionId) {
    if (!confirm('确定要删除这个数据库连接吗？这将影响所有使用此连接的同步任务。')) {
      return;
    }
    
    fetch(`/api/sync/connections/${connectionId}`, {
      method: 'DELETE'
    })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        alert('删除失败: ' + data.error);
      } else {
        loadConnections();
      }
    })
    .catch(error => {
      console.error('Error:', error);
      alert('请求失败，请检查网络连接');
    });
  };
  
  // 删除任务函数
  window.deleteTask = function(taskId) {
    if (!confirm('确定要删除这个同步任务吗？')) {
      return;
    }
    
    fetch(`/api/sync/tasks/${taskId}`, {
      method: 'DELETE'
    })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        alert('删除失败: ' + data.error);
      } else {
        loadTasks();
      }
    })
    .catch(error => {
      console.error('Error:', error);
      alert('请求失败，请检查网络连接');
    });
  };
  
  // 启动任务函数
  window.startTask = function(taskId) {
    fetch(`/api/sync/tasks/${taskId}/start`, {
      method: 'POST'
    })
    .then(response => response.json())
    .then(data => {
      if (data.error) {
        alert('启动失败: ' + data.error);
      } else {
        currentTaskRunId = data.task_run_id;
        currentTaskId = taskId;
        showProgressModal();
        startProgressMonitoring(data.task_run_id);
      }
    })
    .catch(error => {
      console.error('Error:', error);
      alert('请求失败，请检查网络连接');
    });
  };
  
  function showProgressModal() {
    // 重置进度条
    document.getElementById('progressBar').style.width = '0%';
    document.getElementById('progressBar').setAttribute('aria-valuenow', 0);
    document.getElementById('progressCount').textContent = '0 / 0 条记录';
    document.getElementById('progressStatus').textContent = '正在同步...';
    document.getElementById('progressTimer').textContent = '已运行: 00:00:00';
    document.getElementById('progressEta').textContent = '预计剩余时间: --:--:--';
    document.getElementById('progressError').classList.add('d-none');
    document.getElementById('cancelTask').classList.remove('d-none');
    
    // 显示进度模态框
    new bootstrap.Modal(document.getElementById('progressModal')).show();
    
    // 记录开始时间
    progressStartTime = new Date();
  }
  
  function startProgressMonitoring(runId) {
    // 清除之前的定时器
    if (progressInterval) {
      clearInterval(progressInterval);
    }
    
    // 开始新的进度监控
    updateProgress(runId);
    progressInterval = setInterval(() => updateProgress(runId), 2000);
  }
  
  function updateProgress(runId) {
    fetch(`/api/sync/runs/${runId}`)
      .then(response => response.json())
      .then(data => {
        if (data.error) {
          clearInterval(progressInterval);
          document.getElementById('progressError').textContent = '获取进度失败: ' + data.error;
          document.getElementById('progressError').classList.remove('d-none');
          return;
        }
        
        // 更新进度信息
        const progressBar = document.getElementById('progressBar');
        progressBar.style.width = data.progress + '%';
        progressBar.setAttribute('aria-valuenow', data.progress);
        
        document.getElementById('progressCount').textContent = 
          `${data.processed_records} / ${data.total_records} 条记录`;
        
        // 更新状态
        const statusText = getStatusText(data.status);
        document.getElementById('progressStatus').textContent = statusText;
        
        // 更新运行时间
        const now = new Date();
        const elapsedSeconds = Math.floor((now - progressStartTime) / 1000);
        document.getElementById('progressTimer').textContent = 
          '已运行: ' + formatTime(elapsedSeconds);
        
        // 计算预计剩余时间
        if (data.processed_records > 0 && data.total_records > 0) {
          const recordsRemaining = data.total_records - data.processed_records;
          const secondsPerRecord = elapsedSeconds / data.processed_records;
          const estimatedRemainingSeconds = recordsRemaining * secondsPerRecord;
          
          document.getElementById('progressEta').textContent = 
            '预计剩余时间: ' + formatTime(estimatedRemainingSeconds);
        }
        
        // 任务完成或失败时
        if (data.status === 'completed' || data.status === 'failed' || data.status === 'cancelled') {
          clearInterval(progressInterval);
          
          // 更新界面元素
          if (data.status === 'failed') {
            document.getElementById('progressError').textContent = '任务失败: ' + (data.error_message || '未知错误');
            document.getElementById('progressError').classList.remove('d-none');
          }
          
          document.getElementById('cancelTask').classList.add('d-none');
          
          // 一分钟后自动关闭模态框
          setTimeout(() => {
            bootstrap.Modal.getInstance(document.getElementById('progressModal')).hide();
            loadTasks();
          }, 10000);
        }
      })
      .catch(error => {
        console.error('Error:', error);
      });
  }
  
  // 关闭进度模态框时清除定时器
  document.getElementById('closeProgress').addEventListener('click', function() {
    if (progressInterval) {
      clearInterval(progressInterval);
    }
    loadTasks();
  });
});
</script>
</body>
</html> 